﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using DbLinq.Data.Linq;
using Light.Framework.Contract;
using Light.Utility;
using System.Linq.Expressions;
using Light.Framework.Model;

namespace Light.Framework.Linq
{
    /// <summary>
    /// 数据库访问抽象类
    /// </summary>
    /// <typeparam name="TDb"></typeparam>
    /// <typeparam name="TBz"></typeparam>
    public abstract class AbstractDAL<TDb, TBz> : IDataAccess<TBz>
        where TDb : class, new()
        where TBz : class, IEntity, new()
    {


        /// <summary>
        /// 数据表名
        /// </summary>
        protected virtual string TableName
        {
            get
            {
                string[] array = typeof(TDb).ToString().Split('.');
                return array[array.Length - 1];
            }
        }

        /// <summary>
        /// 填充业务实体对象
        /// </summary>
        /// <param name="dbObj">数据库对象</param>
        /// <param name="bzObj">业务实体对象</param>
        public virtual void FillBzEntity(TDb dbObj, TBz bzObj)
        {
            ReflectionHelper.Copy(dbObj, bzObj);
        }

        /// <summary>
        /// 填充数据库实体对象
        /// </summary>
        /// <param name="bzObj">业务实体对象</param>
        /// <param name="dbObj">数据库对象</param>
        public virtual void FillDbEntity(TBz bzObj, TDb dbObj)
        {
            ReflectionHelper.Copy(bzObj, dbObj);
        }

        /// <summary>
        /// 更新，选择，删除用的条件表达式
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public virtual System.Linq.Expressions.Expression<Func<TDb, bool>> GetUpdatePredicate(TBz obj)
        {
            return dbObj => Convert.ToInt32(ReflectionHelper.GetPropertyValue(dbObj, "ID")) == obj.ID;
        }

        /// <summary>
        /// 单一删除（公用方法）
        /// </summary>
        /// <param name="bzObj"></param>
        public virtual void Delete(TBz bzObj)
        {
            string strSql = GetDeleteSqlString(bzObj.ID);
            SQLExecuter.SQLHelper.ExecuteNonQuery(CommandType.Text, strSql, null);
        }

        /// <summary>
        /// 获取删除用的SQL语句
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual string GetDeleteSqlString(int id)
        {
            //return "UPDATE " + TableName + " SET StateID=-1 WHERE ID=" + id + ";";
            return "DELETE FROM " + TableName + " WHERE ID=" + id + ";";
        }

        /// <summary>
        /// 批量删除
        /// </summary>
        /// <param name="IDs"></param>
        public virtual void Delete(List<TBz> bzObjs)
        {

            StringBuilder sqlBuilder = new StringBuilder();
            foreach (var bzObj in bzObjs)
            {

                sqlBuilder.Append(GetDeleteSqlString(bzObj.ID));

            }
            SQLExecuter.SQLHelper.ExecuteNonQuery(CommandType.Text, sqlBuilder.ToString(), null);
        }

        /// <summary>
        /// 插入
        /// </summary>
        /// <param name="bzObj"></param>
        public virtual void Insert(TBz bzObj)
        {
            using (DataContext ctx = SQLExecuter.DataContext)
            {
                TDb dbObj = new TDb();
                FillDbEntity(bzObj, dbObj);
                ctx.GetTable<TDb>().InsertOnSubmit(dbObj);
                ctx.SubmitChanges();
            }
        }

        /// <summary>
        /// 批量插入
        /// </summary>
        /// <param name="bzObjs"></param>
        public virtual void Insert(List<TBz> bzObjs)
        {

            List<TDb> dbObjs = new List<TDb>();
            foreach (var bzObj in bzObjs)
            {
                TDb dbObj = new TDb();
                FillDbEntity(bzObj, dbObj);
                dbObjs.Add(dbObj);
            }

            using (DataContext ctx = SQLExecuter.DataContext)
            {

                ctx.GetTable<TDb>().InsertAllOnSubmit(dbObjs);
                ctx.SubmitChanges();
            }
        }


        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="bzObj"></param>
        public virtual void Update(TBz bzObj)
        {
            using (DataContext ctx = SQLExecuter.DataContext)
            {
                try
                {
                    TDb dbObj = ctx.GetTable<TDb>().Where(GetUpdatePredicate(bzObj)).First();
                    FillDbEntity(bzObj, dbObj);
                }
                catch (Exception ex)
                {
                    throw new NullReferenceException("未找到 " + bzObj.ID + " 对应的数据行，更新失败！" + ex.Message);
                }
                ctx.SubmitChanges();
            }
        }

        /// <summary>
        /// 批量更新
        /// </summary>
        /// <param name="objs"></param>
        public virtual void Update(List<TBz> bzObjs)
        {
            using (DataContext ctx = SQLExecuter.DataContext)
            {
                foreach (var bzObj in bzObjs)
                {
                    try
                    {
                        TDb dbObj = ctx.GetTable<TDb>().Where(GetUpdatePredicate(bzObj)).First();
                        FillDbEntity(bzObj, dbObj);
                    }
                    catch
                    {
                        throw new ArgumentException("未找到对应项，更新失败！");
                    }
                    ctx.SubmitChanges();
                }
            }
        }


        /// <summary>
        /// 获取所有数据
        /// </summary>
        /// <param name="tenantId"></param>
        /// <returns></returns>
        public virtual List<TBz> SelectAll()
        {
            List<TBz> list = new List<TBz>();

            using (DataContext ctx = SQLExecuter.DataContext)
            {
                try
                {
                    var dbObjs = ctx.GetTable<TDb>();
                    foreach (var dbObj in dbObjs)
                    {
                        TBz bzObj = new TBz();
                        FillBzEntity(dbObj, bzObj);
                        list.Add(bzObj);
                    }
                }
                catch (Exception ex)
                {
                    throw new ArgumentException("获取 " + typeof(TBz).ToString() + " 所有数据失败！" + ex.Message);
                }
            }
            return list;
        }


        /// <summary>
        /// 查看详细
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual TBz SelectById(int id)
        {
            TBz bzObj = new TBz() { ID = id };

            using (DataContext ctx = SQLExecuter.DataContext)
            {
                try
                {
                    TDb dbObj = ctx.GetTable<TDb>().Where(GetUpdatePredicate(bzObj)).First();
                    FillBzEntity(dbObj, bzObj);
                }
                catch (Exception ex)
                {
                    throw new NullReferenceException("未找到 " + id + " 对应的数据行，更新失败！" + ex.Message);
                }
            }
            return bzObj;
        }





        public List<TBz> Select(SearchArgs args)
        {
            return new List<TBz>();
        }

    }
}
